package org.n3r.idworker.utils;

import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;

public class Serializes {

  @SuppressWarnings("unchecked")
  public static <T> List<T> readObjects(File file) {
    ArrayList<T> objects = new ArrayList<T>();
    ObjectInputStream objectReader = null;
    FileInputStream fis = null;
    try {
      fis = new FileInputStream(file);
      objectReader = new ObjectInputStream(fis);
        while (true) {
            objects.add((T) objectReader.readObject());
        }

    } catch (EOFException e) {
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      closeQuietly(objectReader);
      closeQuietly(fis);
    }

    return objects;
  }


  @SuppressWarnings("unchecked")
  public static <T> T readObject(File file) {
    ObjectInputStream objectReader = null;
    FileInputStream fis = null;
    try {
      fis = new FileInputStream(file);
      objectReader = new ObjectInputStream(fis);
      return (T) objectReader.readObject();

    } catch (EOFException e) {
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      closeQuietly(objectReader);
      closeQuietly(fis);
    }

    return null;
  }

  public static void writeObject(File file, Object object) {
    ObjectOutputStream objectOutput = null;
    FileOutputStream fos = null;
    try {
      fos = new FileOutputStream(file);
      objectOutput = new ObjectOutputStream(fos);
      objectOutput.writeObject(object);
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      closeQuietly(objectOutput);
      closeQuietly(fos);
    }
  }

  public static void writeObject(FileOutputStream fos, Object object) {
    FileChannel channel = fos.getChannel();
      if (!channel.isOpen()) {
          throw new RuntimeException("channel is closed");
      }

    try {
      channel.position(0);
      ObjectOutputStream objectOutput = new ObjectOutputStream(fos);
      objectOutput.writeObject(object);
      fos.flush();
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
    }
  }

  public static void writeObjects(File file, Object... objects) {
    ObjectOutputStream objectOutput = null;
    FileOutputStream fos = null;
    try {
      fos = new FileOutputStream(file);
      objectOutput = new ObjectOutputStream(fos);

        for (Object object : objects) {
            objectOutput.writeObject(object);
        }
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      closeQuietly(objectOutput);
      closeQuietly(fos);
    }

  }

  public static void closeQuietly(OutputStream os) {
      if (os != null) {
          try {
              os.close();
          } catch (IOException e) {
              // ignore
          }
      }
  }


  public static void closeQuietly(InputStream is) {
      if (is != null) {
          try {
              is.close();
          } catch (IOException e) {
              // ignore
          }
      }

  }
}
